﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

using G.Runtime;
using GameControls;
using G.Model;

namespace GameRuntimeControls
{
    public partial class GameSpaceView 
        : UserControl, IDisposable, GameUserControl
    {
        public delegate void ElementHandler(GameElement element);
        public delegate void SpaceChangedHandler(GameSpace space);
        public event ElementHandler ElementAdded;
        public event SpaceChangedHandler SpaceChanged;
        
        private readonly Dictionary<string, Image> _ImageDictionary;
        
        private BoardShapeContainer _ShapeContainer;
        private GameDisplayerPT _GameDisplayerPT;
        private HasGameSpace _HasGame;
        private int _SquareSize;
        private BoardLinePainter _BoardLinePainter;
        
        public GameSpaceView()
        {
            InitializeComponent();
            
            _SquareSize = 50;
            _ShapeContainer = new BoardShapeContainer(this, _SquareSize);
            this.Paint += _ShapeContainer.OnPaint;
            this.MouseClick += _ShapeContainer.OnMouseClick;
            _ImageDictionary = new Dictionary<string, Image>();

            CreateImageDictionary();
        }
        
        private void CreateImageDictionary()
        {
            _ImageDictionary.Clear();
            foreach (string key in _ImageList.Images.Keys) 
            {
                Image image = _ImageList.Images[key];
                Image thumb = image.GetThumbnailImage(
                    _SquareSize-2, _SquareSize-2, GetThumbnailImageAbort,
                    System.IntPtr.Zero);
                _ImageDictionary.Add(key, thumb);
            }
        }
        
        bool GetThumbnailImageAbort()
        {
            return false;
        }
        
        [Browsable(false)]
        public Dictionary<string, Image> ImageDictionary
        {
            get { return _ImageDictionary; }
        }
        
        protected override void Dispose(bool disposing)
        {
            this.Paint -= _ShapeContainer.OnPaint;
            this.MouseClick -= _ShapeContainer.OnMouseClick;
            
            if (disposing) 
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            
            base.Dispose(disposing);
        }
        
        [Browsable(false)]
        public BoardShapeContainer ShapeContainer
        {
            get { return _ShapeContainer; }
        }
        
        public ImageList ImageList
        {
            get { return this._ImageList; }
            set 
            {
                _ImageList = value;
                Invalidate();
            }
        }
        
        public HasGameSpace GameSpace
        {
            get { return _HasGame; }
            set
            {
                if (_HasGame != value)
                {
                    _HasGame = value;
                    SetupDisplayer();
                }
            }
        }
        
        public int SquareSize
        {
            get { return _SquareSize; }
            set
            {
                if (_SquareSize != value)
                {
                    _SquareSize = value;
                    CreateImageDictionary();
                    SetupDisplayer();
                }
            }
        }
        
        [Browsable(false)]
        public GameDisplayer GameDisplayer
        {
            get { return _GameDisplayerPT; }
        }

        private void SetupDisplayer()
        {
            if (_ShapeContainer == null)
            {
                return;
            }
            
            if (_GameDisplayerPT != null)
            {
                this.Paint -= _ShapeContainer.OnPaint;
                this.MouseClick -= _ShapeContainer.OnMouseClick;
                _ShapeContainer = new BoardShapeContainer(this, _SquareSize);
                this.Paint += _ShapeContainer.OnPaint;
                this.MouseClick += _ShapeContainer.OnMouseClick;
                _BoardLinePainter.Dispose();
                _GameDisplayerPT.Game.Elements.ElementAddedEvent -= OnElementAddedEvent;
                _GameDisplayerPT.Dispose();
            }
            
            if (_HasGame != null)
            {
                _GameDisplayerPT = new GameDisplayerPT(
                    _HasGame.Game, _ShapeContainer, _SquareSize);
                _BoardLinePainter = new BoardLinePainter(
                    this, _HasGame.Game.Def, _SquareSize);
                _GameDisplayerPT.Game.Elements.ElementAddedEvent += OnElementAddedEvent;
                FireSpaceChanged();
            }
            
            base.Invalidate();
        }
        
        private void OnElementAddedEvent(GameElement subject)
        {
            if (ElementAdded != null)
            {
                ElementAdded(subject);
            }
        }
        
        private void FireSpaceChanged()
        {
            if (SpaceChanged != null)
            {
                SpaceChanged(_HasGame.Game);
            }
        }
        
    }
}
